package com.cjlgb.design.upms.receiver;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cjlgb.design.common.mybatis.bean.PageBean;
import com.cjlgb.design.upms.api.entity.*;
import com.cjlgb.design.upms.api.channel.AccountOutputChannel;
import com.cjlgb.design.upms.service.SysMenuService;
import com.cjlgb.design.upms.service.SysRoleMenuService;
import com.cjlgb.design.upms.service.SysUserRoleService;
import com.cjlgb.design.upms.service.SysUserService;
import com.cjlgb.design.upms.channel.SysRoleChannel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author WFT
 * @date 2019/8/29
 * description: 系统角色异步接口消费逻辑
 */
@Slf4j
@Component
@RequiredArgsConstructor
@EnableBinding(value = SysRoleChannel.class)
public class SysRoleReceiver {

    private final SysUserRoleService userRoleService;
    private final SysUserService userService;
    private final AccountOutputChannel accountOutputChannel;
    private final SysRoleMenuService roleMenuService;
    private final SysMenuService menuService;

    /**
     * 监听角色被重新授权
     * @param roleId 角色Id
     */
    @StreamListener(value = SysRoleChannel.INPUT, condition = "headers['method']=='authorize'")
    public void listenerAuthorize(Long roleId){
        //  分页获取当前角色Id所绑定的账号
        int current = 0;
        PageBean<SysUserRole> pageBean = new PageBean<>(current,100);
        while (true){
            pageBean.setCurrent(++current);
            //  得到账号Id
            IPage<SysUserRole> page = this.userRoleService.pagingQuery(pageBean, roleId);
            List<Long> accountIds = page.getRecords().stream()
                    .map(SysUserRole::getAccountId).collect(Collectors.toList());
            if (!accountIds.isEmpty()) {
                //  获取账号名称
                List<String> nameList = this.userService.selectByAccountIds(accountIds)
                        .stream().map(SysUserInfo::getAccountName).collect(Collectors.toList());
                //  更新账号缓存
                this.accountOutputChannel.output().send(
                        MessageBuilder.withPayload(nameList)
                                .setHeader("method", "deleteCache").build()
                );
            }
            //  结束循环
            if (page.getPages() <= current){
                break;
            }
        }
    }

    /**
     * 监听角色被删除
     * @param roleIds 角色Id列表
     */
    @StreamListener(value = SysRoleChannel.INPUT, condition = "headers['method']=='delete'")
    public void listenerDelete(Collection<Long> roleIds){
        //  删除角色与菜单之间的关联
        this.roleMenuService.deleteByRoleIds(roleIds);
        //  通知关联的账号更新缓存
        roleIds.forEach(this::listenerAuthorize);
        //  删除角色与账号之间的关联
        this.userRoleService.deleteByRoleIds(roleIds);
    }

    /**
     * 监听角色的权限列表发生更改
     * @param role 角色信息
     */
    @StreamListener(value = SysRoleChannel.INPUT, condition = "headers['method']=='changeAuthorities'")
    public void listenerChangeAuthorities(SysRole role){
        //  删除角色原先与菜单之间的关联
        this.roleMenuService.deleteByRoleId(role.getId());
        //  添加角色与菜单之间的关联
        if (!role.getAuthorities().isEmpty()){
            //  角色与菜单之间的关联列表
            Collection<SysRoleMenu> roleMenus = new ArrayList<>();
            //  菜单Id列表
            Collection<Long> menuIds = role.getAuthorities();
            int type = 3;
            for (int i = type; i > 0; i--){
                //  查询权限列表 [按钮权限，菜单，模块] 依次查询
                Collection<SysMenu> list = this.menuService.selectByIds(role.getAuthorities(),i);
                //  清空Id列表
                menuIds.clear();
                //  遍历列表
                list.forEach(menu -> {
                    if (!menuIds.contains(menu.getPid())){
                        menuIds.add(menu.getPid());
                    }
                    //  创建角色与菜单之间的关联
                    roleMenus.add(new SysRoleMenu(role.getId(),menu.getId(),menu.getType()));
                });
            }
            if (!roleMenus.isEmpty()) {
                //  保存
                this.roleMenuService.saveBatch(roleMenus);
                //  通知关联的账号更新缓存
                this.listenerAuthorize(role.getId());
            }
        }
    }



}
